#!/bin/bash

UPSTREAM=$1
shift
TARGET=$1

set -e
COCCI_CACHE_DIR=transform.d/cocci-cache
TRANSFORMATIONS=transform.d/*
DIR=${TARGET%/*}
TMP=$TARGET.tmp

msg()
{
    if test "$V"; then
	printf "$@"
    else
	echo -n .
    fi
}

mkdir -p $DIR
cp $UPSTREAM $TMP

for TRANS in $TRANSFORMATIONS; do
    test -d $TRANS && continue
    EXT=${TRANS##*.}
    TRANS_NAME=${TRANS##*/}
    TARGET_FILE=${TARGET##*/}
    case $EXT in
	patch)
	    FIRST_LINE_OF_PATCH="$(grep ^diff < $TRANS)"
	    PATCH_TARGET=${FIRST_LINE_OF_PATCH##*/}
	    if [ $PATCH_TARGET = $TARGET_FILE ]; then
		msg " PATCH    : %-40s %s\n" $TRANS_NAME $TARGET
		patch -N --batch --silent $TMP $TRANS
	    fi
	;;
	cocci)
	    mkdir -p $COCCI_CACHE_DIR/$TARGET_FILE
	    CACHE_FILE=$COCCI_CACHE_DIR/$TARGET_FILE/$TRANS_NAME
	    CACHE_FILE=${CACHE_FILE/.cocci/.patch}
	    if test -e $CACHE_FILE && \
	       test $CACHE_FILE -nt $TRANS && \
	       test $CACHE_FILE -nt $UPSTREAM && \
	       patch --batch --dry-run --fuzz 0 --silent $TMP $CACHE_FILE 2> /dev/null > /dev/null; then
		msg " CACHED CO: %-40s %s\n" $TRANS_NAME $TARGET
		patch --batch --fuzz 0 --silent $TMP $CACHE_FILE
	    else
		msg " GEN COCCI: %-40s %s\n" $TRANS_NAME $TARGET
		rm -f "$CACHE_FILE"
		spatch --sp-file $TRANS --verbose-parsing --in-place $TMP > $CACHE_FILE.tmp 2> $CACHE_FILE.err
		rm $CACHE_FILE.err
		mv "$CACHE_FILE.tmp" "$CACHE_FILE"
	    fi
	;;
	*)
	    if test -x $TRANS; then
		msg " TRANSFORM: %-40s %s\n" $TRANS_NAME $TARGET
		$TRANS $TMP
	    else
		msg " IGNORED  : %-40s %s\n" $TRANS_NAME $TARGET
	    fi
    esac
done
mv $TMP $TARGET
msg " MOVE     : %-40s %s\n" $TMP $TARGET
